package znet

import (
	"fmt"
	"net"
	"zinx/utils"
	"zinx/ziface"
)

type Server struct {
	// 服务器的名称
	Name string
	// 服务器的ip版本
	IpVersion string
	// 服务器监听的ip
	Ip string
	// 服务器监听的端口
	Port int
	// 当前Server的消息管理模块，用来绑定MsgId和对应的处理业务的API关系
	MsgHandler ziface.IMsgHandler
	// 该server的链接管理器
	ConnMgr ziface.IConnManager
	// 该server创建链接之后自动调用的hook函数
	OnConnStart func(conn ziface.IConnection)
	// 该server销毁链接之前自动调用的hook函数
	OnConnStop func(conn ziface.IConnection)
}

// 启动
func (s *Server) Start() {
	fmt.Printf("[Start] Server Name: %s, Listener at IP: %s, Port: %d is starting \n", s.Name, s.Ip, s.Port)

	go func() {
		// 开启消息队列及worker工作池
		s.MsgHandler.StartWorkerPool()
		// 获取一个tcp 的Addr
		addr, err := net.ResolveTCPAddr(s.IpVersion, fmt.Sprintf("%s:%d", s.Ip, s.Port))
		if err != nil {
			fmt.Println("resolve tcp address error: ", err)
			return
		}
		// 监听服务器的地址
		listener, err := net.ListenTCP(s.IpVersion, addr)
		if err != nil {
			fmt.Println("listen address error: ", err)
			return
		}
		fmt.Println("start Zinx server ", s.Name, " success, listening...")

		// 阻塞的等待客户端的链接，处理客户端链接业务(读写)
		var cid uint32
		cid = 0
		for {
			// 如果客户端链接过来，阻塞会返回
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept error: ", err)
				continue
			}
			// 设置最大链接个数的判断，如果超过最大的链接，则关闭该链接
			if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
				// TODO 给客户端相应一个超出最大链接的错误包
				fmt.Println("======= Too Many Connections======== maxConn = ", utils.GlobalObject.MaxConn)
				conn.Close()
				continue
			}

			// 已经与客户端建立链接，做一些业务，做一个最基本的最大512字节长度的回显业务
			// 与conn进行绑定， 得到链接模块
			dealConn := NewConnection(s, conn, cid, s.MsgHandler)
			cid++

			go dealConn.Start()
		}
	}()

}

// 停止
func (s *Server) Stop() {
	//TODO 做一些服务器的资源，状态或者一些已经开辟的链接信息 进行停止或者回收
	fmt.Println("Stop server name: ", s.Name)
	s.ConnMgr.ClearConn()
}

// 运行
func (s *Server) Serve() {
	// 启动server的服务功能
	s.Start()
	//TODO 做一些启动服务器之后的额外的业务

	// 阻塞的状态
	select {}
}

func (s *Server) AddRouter(msgId uint32, router ziface.IRouter) {
	s.MsgHandler.AddRouter(msgId, router)
	fmt.Println("Add Router Success..")
}

// 获取conn管理器
func (s *Server) GetConnMgr() ziface.IConnManager {
	return s.ConnMgr
}

// 注册OnConnStart的hook函数
func (s *Server) SetOnConnStart(hookFunc func(conn ziface.IConnection)) {
	s.OnConnStart = hookFunc
}

// 注册OnConnStop的hook函数
func (s *Server) SetOnConnStop(hookFunc func(conn ziface.IConnection)) {
	s.OnConnStop = hookFunc
}

// 调用OnConnStart的hook函数
func (s *Server) CallOnConnStart(conn ziface.IConnection) {
	if s.OnConnStart != nil {
		fmt.Println("------> call OnConnStart")
		s.OnConnStart(conn)
	}
}

// 调用OnConnStop的hook函数
func (s *Server) CallOnConnStop(conn ziface.IConnection) {
	if s.OnConnStop != nil {
		fmt.Println("------> call OnConnStop")
		s.OnConnStop(conn)
	}
}

func NewServer(name string) ziface.Isever {
	s := &Server{
		Name:       utils.GlobalObject.Name,
		IpVersion:  "tcp4",
		Ip:         utils.GlobalObject.Host,
		Port:       utils.GlobalObject.TcpPort,
		MsgHandler: NewMsgHandler(),
		ConnMgr:    NewConnManager(),
	}

	return s
}
